home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / iface.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  16KB  |  656 lines

  1. /* IP interface control and configuration routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by PA0GRI 
  5.  */
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "config.h"
  9. #include "mbuf.h"
  10. #include "proc.h"
  11. #include "iface.h"
  12. #include "ip.h"
  13. #include "netuser.h"
  14. #include "ax25.h"
  15. #ifdef ETHER
  16. #include "enet.h"
  17. #endif
  18. #include "arp.h"
  19. #include "pktdrvr.h"
  20. #include "cmdparse.h"
  21. #include "commands.h"
  22. #include "nr4.h"
  23. #include "socket.h"
  24. #include "mailbox.h" 
  25.  
  26. #ifdef NETROM
  27. extern struct iface *Nr_iface;
  28. #endif
  29.  
  30. static void showiface __ARGS((struct iface *ifp));
  31. static int mask2width __ARGS((int32 mask));
  32. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  33. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  34. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  35. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  36. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  37. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  38. static int ifforw __ARGS((int argc,char *argv[],void *p));
  39. static int ifencap __ARGS((int argc,char *argv[],void *p));
  40. static int ifdescr __ARGS((int argc,char *argv[],void *p));
  41. static int ifpaclen __ARGS((int argc,char *argv[],void *p));
  42.  
  43. /* Interface list header */
  44. struct iface *Ifaces = &Loopback;
  45.  
  46. /* Loopback pseudo-interface */
  47. struct iface Loopback = {
  48. #ifdef ENCAP
  49.     &Encap,     /* Link to next entry */
  50. #else
  51.     NULLIF,
  52. #endif
  53.     "loopback", /* name     */
  54.     NULLCHAR,   /* description */
  55.     0x7f000001L,    /* addr         127.0.0.1 */
  56.     0xffffffffL,    /* broadcast    255.255.255.255 */
  57.     0xffffffffL,    /* netmask      255.255.255.255 */
  58.     MAXINT16,       /* mtu          No limit */
  59.     0,          /* AX.25 paclen, if applicable */
  60.     0,      /* flags    */
  61.     0,      /* quality  */
  62.     0,              /* trace        */
  63.     NULLCHAR,       /* trfile       */
  64.     NULLFILE,       /* trfp         */
  65.     NULLIF,         /* forw         */
  66.     NULLPROC,       /* rxproc       */
  67.     NULLPROC,       /* txproc       */
  68.     NULLPROC,       /* supv         */
  69.     0,              /* dev          */
  70.     (int32(*)__FARGS((struct iface*,int,int,int32)))NULL,/* (*ioctl)     */
  71.     NULLFP((struct iface*,int,int32)),         /* (*iostatus)  */
  72.     NULLFP((struct iface*)),         /* (*stop)      */
  73.     NULLCHAR,       /* hwaddr       */
  74.     NULL,           /* extension    */
  75.     CL_NONE,        /* type         */
  76.     0,              /* xdev         */
  77.     0,              /* port         */
  78.     &Iftypes[0],    /* iftype       */
  79.     NULLFP((struct mbuf*,struct iface*,int32,int,int,int,int)),/* (*send)      */
  80.     NULLFP((struct iface*,char*,char*,int16,struct mbuf*)),/* (*output)    */
  81.     NULLFP((struct iface*,struct mbuf*)),         /* (*raw)       */
  82.     NULLVFP((struct iface*)),        /* (*show)      */
  83.     NULLFP((struct iface*,struct mbuf*)),         /* (*discard)   */
  84.     NULLFP((struct iface*,struct mbuf*)),         /* (*echo)      */
  85.     0,              /* ipsndcnt     */
  86.     0,              /* rawsndcnt    */
  87.     0,              /* iprecvcnt    */
  88.     0,              /* rawrcvcnt    */
  89.     0,              /* lastsent     */
  90.     0,              /* lastrecv     */
  91. };
  92.  
  93. #ifdef ENCAP
  94. /* Encapsulation pseudo-interface */
  95. struct iface Encap = {
  96.     NULLIF,
  97.     "encap",        /* name         */
  98.     NULLCHAR,   /* description */
  99.     INADDR_ANY,     /* addr         0.0.0.0 */
  100.     0xffffffffL,    /* broadcast    255.255.255.255 */
  101.     0xffffffffL,    /* netmask      255.255.255.255 */
  102.     MAXINT16,       /* mtu          No limit */
  103.     0,          /* AX.25 paclen, if applicable */
  104.     0,      /* flags    */
  105.     0,      /* quality  */
  106.     0,              /* trace        */
  107.     NULLCHAR,       /* trfile       */
  108.     NULLFILE,       /* trfp         */
  109.     NULLIF,         /* forw         */
  110.     NULLPROC,       /* rxproc       */
  111.     NULLPROC,       /* txproc       */
  112.     NULLPROC,       /* supv         */
  113.     0,              /* dev          */
  114.     (int32(*)__FARGS((struct iface*,int,int,int32)))NULL,/* (*ioctl)     */
  115.     NULLFP((struct iface*,int,int32)),         /* (*iostatus)  */
  116.     NULLFP((struct iface*)),         /* (*stop)      */
  117.     NULLCHAR,       /* hwaddr       */
  118.     NULL,           /* extension    */
  119.     CL_NONE,        /* type         */
  120.     0,              /* xdev         */
  121.     0,              /* port         */
  122.     &Iftypes[0],    /* iftype       */
  123.     ip_encap,       /* (*send)      */
  124.     NULLFP((struct iface*,char*,char*,int16,struct mbuf*)),/* (*output)    */
  125.     NULLFP((struct iface*,struct mbuf*)),         /* (*raw)       */
  126.     NULLVFP((struct iface*)),        /* (*show)      */
  127.     NULLFP((struct iface*,struct mbuf*)),         /* (*discard)   */
  128.     NULLFP((struct iface*,struct mbuf*)),         /* (*echo)      */
  129.     0,              /* ipsndcnt     */
  130.     0,              /* rawsndcnt    */
  131.     0,              /* iprecvcnt    */
  132.     0,              /* rawrcvcnt    */
  133.     0,              /* lastsent     */
  134.     0,              /* lastrecv     */
  135. };
  136. #endif /*ENCAP*/
  137.  
  138. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  139.  
  140. struct cmds Ifcmds[] = {
  141.     "broadcast",            ifbroad,        0,      2,      NULLCHAR,
  142.     "description",      ifdescr,    0,  0,  NULLCHAR,
  143.     "encapsulation",        ifencap,        0,      2,      NULLCHAR,
  144.     "forward",              ifforw,         0,      2,      NULLCHAR,
  145.     "ipaddress",            ifipaddr,       0,      2,      NULLCHAR,
  146.     "linkaddress",          iflinkadr,      0,      2,      NULLCHAR,
  147.     "mtu",                  ifmtu,          0,      2,      NULLCHAR,
  148.     "netmask",              ifnetmsk,       0,      2,      NULLCHAR,
  149. #ifdef AX25
  150.     "paclen",       ifpaclen,   0,  2,  NULLCHAR,
  151. #endif
  152.     "rxbuf",        ifrxbuf,    0,  2,  NULLCHAR,
  153.     NULLCHAR,
  154. };
  155.  
  156. /* Set interface parameters */
  157. int
  158. doifconfig(argc,argv,p)
  159. int argc;
  160. char *argv[];
  161. void *p;
  162. {
  163.     struct iface *ifp;
  164.     int i;
  165.  
  166.     if(argc < 2){
  167.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  168.             showiface(ifp);
  169.         return 0;
  170.     }
  171.     if((ifp = if_lookup(argv[1])) == NULLIF){
  172.     tprintf(Badinterface,argv[1]);
  173.         return 1;
  174.     }
  175.     if(argc == 2){
  176.         showiface(ifp);
  177.         if ( ifp->show != NULLVFP((struct iface*)) ) {
  178.             (*ifp->show)(ifp);
  179.         }
  180.         return 0;
  181.     }
  182.     if(argc == 3){
  183.         tprintf("Argument missing\n");
  184.         return 1;
  185.     }
  186.     for(i=2;i<argc-1;i+=2)
  187.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  188.  
  189.     return 0;
  190. }
  191.  
  192. /* Set interface IP address */
  193. static int
  194. ifipaddr(argc,argv,p)
  195. int argc;
  196. char *argv[];
  197. void *p;
  198. {
  199.     struct iface *ifp = p;
  200.  
  201.     /* Do not allow loopback iface to be changed ! - WG7J */
  202.     if(ifp == &Loopback) {
  203.     tputs("Cannot change IP address !\n");
  204.     return 0;
  205.     }
  206.     ifp->addr = resolve(argv[1]);
  207.     return 0;
  208. }
  209.  
  210.  
  211. /* Set link (hardware) address */
  212. static int
  213. iflinkadr(argc,argv,p)
  214. int argc;
  215. char *argv[];
  216. void *p;
  217. {
  218.     struct iface *ifp = p;
  219.  
  220.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  221.         tprintf("Can't set link address\n");
  222.         return 1;
  223.     }
  224.     if(ifp->hwaddr != NULLCHAR)
  225.         free(ifp->hwaddr);
  226.     ifp->hwaddr = mallocw((unsigned)ifp->iftype->hwalen);
  227.     (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  228. #ifdef MAILBOX
  229. #ifdef NETROM
  230.     if(ifp == Nr_iface) /*the netrom call just got changed! - WG7J*/
  231.     setmbnrid();
  232. #endif
  233. #endif
  234.     return 0;
  235. }
  236.  
  237. /* Set interface broadcast address. This is actually done
  238.  * by installing a private entry in the routing table.
  239.  */
  240. static int
  241. ifbroad(argc,argv,p)
  242. int argc;
  243. char *argv[];
  244. void *p;
  245. {
  246.     struct iface *ifp = p;
  247.     struct route *rp;
  248.  
  249.     rp = rt_blookup(ifp->broadcast,32);
  250.     if(rp != NULLROUTE && rp->iface == ifp)
  251.         rt_drop(ifp->broadcast,32);
  252.     ifp->broadcast = resolve(argv[1]);
  253.     rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  254.     return 0;
  255. }
  256.  
  257. /* Set the network mask. This is actually done by installing
  258.  * a routing entry.
  259.  */
  260. static int
  261. ifnetmsk(argc,argv,p)
  262. int argc;
  263. char *argv[];
  264. void *p;
  265. {
  266.     struct iface *ifp = p;
  267.     struct route *rp;
  268.  
  269.     /* Remove old entry if it exists */
  270.     rp = rt_blookup(ifp->addr & ifp->netmask,(unsigned)mask2width(ifp->netmask));
  271.     if(rp != NULLROUTE)
  272.         rt_drop(rp->target,rp->bits);
  273.  
  274.     ifp->netmask = htol(argv[1]);
  275.     rt_add(ifp->addr,(unsigned)mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  276.     return 0;
  277. }
  278.  
  279. /* Command to set interface encapsulation mode */
  280. static int
  281. ifencap(argc,argv,p)
  282. int argc;
  283. char *argv[];
  284. void *p;
  285. {
  286.     struct iface *ifp = p;
  287.  
  288.     if(setencap(ifp,argv[1]) != 0){
  289.         tprintf("Encapsulation mode '%s' unknown\n",argv[1]);
  290.         return 1;
  291.     }
  292.     return 0;
  293. }
  294. /* Function to set encapsulation mode */
  295. int
  296. setencap(ifp,mode)
  297. struct iface *ifp;
  298. char *mode;
  299. {
  300.     struct iftype *ift;
  301.  
  302.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  303.         if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  304.             break;
  305.     if(ift->name == NULLCHAR){
  306.         return -1;
  307.     }
  308.     ifp->iftype = ift;
  309.     ifp->send = ift->send;
  310.     ifp->output = ift->output;
  311.     ifp->type = ift->type;
  312. #ifdef AX25
  313.     if(ift->type == CL_AX25) {
  314.     ifp->paclen = Paclen; /* default to the 'ax25 paclen' value */
  315.     ifp->flags += AX25_BEACON+MAIL_BEACON+AX25_DIGI+LOG_AXHEARD+LOG_IPHEARD;
  316.     }
  317. #endif
  318.     return 0;
  319. }
  320. /* Set interface receive buffer size */
  321. static int
  322. ifrxbuf(argc,argv,p)
  323. int argc;
  324. char *argv[];
  325. void *p;
  326. {
  327.     return 0;       /* To be written */
  328. }
  329.  
  330. /* Set interface Maximum Transmission Unit */
  331. static int
  332. ifmtu(argc,argv,p)
  333. int argc;
  334. char *argv[];
  335. void *p;
  336. {
  337.     struct iface *ifp = p;
  338.  
  339.     ifp->mtu = atoi(argv[1]);
  340. #ifdef NETROM
  341.     /* Make sure NETROM mtu <= 236 ! - WG7J */
  342.     if(ifp == Nr_iface)
  343.     if(Nr_iface->mtu > NR4MAXINFO)
  344.         Nr_iface->mtu = NR4MAXINFO;
  345. #endif
  346.     return 0;
  347. }
  348.  
  349. #ifdef AX25
  350.  
  351. /* Set interface AX.25 Paclen, and adjust the NETROM mtu for the
  352.  * smallest paclen. - WG7J
  353.  */
  354. static int
  355. ifpaclen(argc,argv,p)
  356. int argc;
  357. char *argv[];
  358. void *p;
  359. {
  360.     struct iface *ifp = p;
  361. #ifdef NETROM
  362.     int tmp;
  363. #endif
  364.  
  365.     if(ifp->iftype->type == CL_AX25) {
  366.     ifp->paclen = atoi(argv[1]);
  367. #ifdef NETROM
  368.     if(ifp->flags & IS_NR_IFACE)
  369.         if((tmp=ifp->paclen - 20) < Nr_iface->mtu)
  370.         Nr_iface->mtu = tmp;
  371. #endif
  372.     } else
  373.     tputs("Not ax.25 interface!\n");
  374.     return 0;
  375. }
  376. #endif
  377.  
  378. /* Set interface forwarding */
  379. static int
  380. ifforw(argc,argv,p)
  381. int argc;
  382. char *argv[];
  383. void *p;
  384. {
  385.     struct iface *ifp = p;
  386.  
  387.     ifp->forw = if_lookup(argv[1]);
  388.     if(ifp->forw == ifp)
  389.         ifp->forw = NULLIF;
  390.     return 0;
  391. }
  392.  
  393. /*give a little description for each interface - WG7J*/
  394. static int
  395. ifdescr(argc,argv,p)
  396. int argc;
  397. char *argv[];
  398. void *p;
  399. {
  400.     struct iface *ifp = p;
  401.  
  402. #ifdef NETROM
  403. #ifdef ENCAP
  404.     if((ifp == &Loopback) || (ifp == &Encap) || (ifp == Nr_iface))
  405. #else
  406.     if((ifp == &Loopback) || (ifp == Nr_iface))
  407. #endif /*ENCAP*/
  408. #else  /*NETROM*/
  409. #ifdef ENCAP
  410.     if((ifp == &Loopback) || (ifp == &Encap))
  411. #else
  412.     if(ifp == &Loopback)
  413. #endif /*ENCAP*/
  414. #endif /*NETROM*/
  415.     return 0;
  416.  
  417.     if(ifp->descr != NULLCHAR){
  418.     free(ifp->descr);
  419.     ifp->descr = NULLCHAR;        /* reset the pointer */
  420.     }
  421.     if(!strlen(argv[1]))
  422.     return 0;           /* clearing the buffer */
  423.  
  424.     ifp->descr = mallocw(strlen(argv[1])+5); /* allow for the EOL char etc */
  425.     strcpy(ifp->descr, argv[1]);
  426.     strcat(ifp->descr, "\n");         /* add the EOL char */
  427.  
  428.     return 0;
  429. }
  430.  
  431.  
  432.  
  433. /* Display the parameters for a specified interface */
  434. static void
  435. showiface(ifp)
  436. register struct iface *ifp;
  437. {
  438.     char tmp[25];
  439.  
  440.     tprintf("%-10s IP addr %s MTU %u Link encap ",ifp->name,
  441.      inet_ntoa(ifp->addr),(int)ifp->mtu);
  442.     if(ifp->iftype == NULLIFT){
  443.         tprintf("not set\n");
  444.     } else {
  445.         tprintf("%s\n",ifp->iftype->name);
  446.     if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR) {
  447.         tprintf("           Link addr %s",
  448.              (*ifp->iftype->format)(tmp,ifp->hwaddr));
  449.         if(ifp->iftype->type == CL_AX25)
  450.         tprintf("   Paclen %d\n",(int)ifp->paclen);
  451.         else
  452.         tputc('\n');
  453.     }
  454.     }
  455.     tprintf("           flags 0x%lx trace 0x%x netmask 0x%08lx broadcast %s\n",
  456.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  457.     if(ifp->forw != NULLIF)
  458.         tprintf("           output forward to %s\n",ifp->forw->name);
  459.     tprintf("           sent: ip %lu tot %lu idle %s\n",
  460.      ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  461.     tprintf("           recv: ip %lu tot %lu idle %s\n",
  462.      ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  463.     if(ifp->descr != NULLCHAR)
  464.     tprintf("           descr: %s",ifp->descr);
  465.  
  466. }
  467.  
  468. /* Command to detach an interface */
  469. int
  470. dodetach(argc,argv,p)
  471. int argc;
  472. char *argv[];
  473. void *p;
  474. {
  475.     register struct iface *ifp;
  476.  
  477.     if((ifp = if_lookup(argv[1])) == NULLIF){
  478.     tprintf(Badinterface,argv[1]);
  479.         return 1;
  480.     }
  481.     if(if_detach(ifp) == -1)
  482.         tprintf("Can't detach loopback or encap interface\n");
  483.     return 0;
  484. }
  485. /* Detach a specified interface */
  486. int
  487. if_detach(ifp)
  488. register struct iface *ifp;
  489. {
  490.     struct iface *iftmp;
  491.     struct route *rp,*rptmp;
  492.     int i,j;
  493.     struct ax_route *axr, *axr1;
  494.     struct arp_tab *ap, *ap1;
  495.  
  496. #ifdef ENCAP
  497.     if(ifp == &Loopback || ifp == &Encap)
  498. #else
  499.     if(ifp == &Loopback)
  500. #endif
  501.         return -1;
  502.  
  503. #ifdef AX25
  504.     /* Drop all ax25 routes that points to this interface */
  505.     for(axr = Ax_routes; axr != NULLAXR; axr = axr1) {
  506.         axr1 = axr->next;/* Save the next pointer */
  507.         if(axr->iface == ifp)
  508.             ax_drop(axr->target, ifp);
  509.         /* axr will be undefined after ax_drop() */
  510.     }
  511. #endif
  512.  
  513.     /* Drop all ARP's that point to this interface */
  514.     for(i = 0; i < HASHMOD; ++i)
  515.         for(ap = Arp_tab[i]; ap != NULLARP; ap = ap1) {
  516.         ap1 = ap->next;    /* Save the next pointer */
  517.         if(ap->iface == ifp)
  518.             arp_drop(ap);
  519.         /* ap will be undefined after arp_drop() */
  520.         }
  521.  
  522.  
  523.     /* Drop all routes that point to this interface */
  524.     if(R_default.iface == ifp)
  525.         rt_drop(0L,0);  /* Drop default route */
  526.  
  527.     for(i=0;i<HASHMOD;i++){
  528.         for(j=0;j<32;j++){
  529.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  530.                 /* Save next pointer in case we delete this entry */
  531.                 rptmp = rp->next;
  532.                 if(rp->iface == ifp)
  533.                     rt_drop(rp->target,rp->bits);
  534.             }
  535.         }
  536.     }
  537.     /* Unforward any other interfaces forwarding to this one */
  538.     for(iftmp = Ifaces;iftmp != NULLIF;iftmp = iftmp->next){
  539.         if(iftmp->forw == ifp)
  540.             iftmp->forw = NULLIF;
  541.     }
  542.  
  543.     /* Call device shutdown routine, if any */
  544.     if(ifp->stop != NULLFP((struct iface*)))
  545.         (*ifp->stop)(ifp);
  546.  
  547.     killproc(ifp->rxproc);
  548.     killproc(ifp->txproc);
  549.     killproc(ifp->supv);
  550.  
  551. #ifdef NETROM
  552.     /*make sure that the netrom interface is properly detached
  553.      *fixed 11/15/91, Johan. K. Reinalda, WG7J/PA3DIS
  554.      */
  555.     if(strcmp(ifp->name,"netrom") == 0) {
  556.     for(iftmp=Ifaces;iftmp;iftmp=iftmp->next)
  557.         iftmp->flags &= ~IS_NR_IFACE; /* this 'resets' active interfaces */
  558.     Nr_iface = NULLIF;
  559.     }
  560. #endif
  561.  
  562.     /* Free allocated memory associated with this interface */
  563.     if(ifp->name != NULLCHAR)
  564.         free(ifp->name);
  565.     if(ifp->hwaddr != NULLCHAR)
  566.         free(ifp->hwaddr);
  567.  
  568.     /* Remove from interface list */
  569.     if(ifp == Ifaces){
  570.         Ifaces = ifp->next;
  571.     } else {
  572.         /* Search for entry just before this one
  573.          * (necessary because list is only singly-linked.)
  574.          */
  575.         for(iftmp = Ifaces;iftmp != NULLIF ;iftmp = iftmp->next)
  576.             if(iftmp->next == ifp)
  577.                 break;
  578.         if(iftmp != NULLIF && iftmp->next == ifp)
  579.             iftmp->next = ifp->next;
  580.     }
  581.     /* Finally free the structure itself */
  582.     free((char *)ifp);
  583.     return 0;
  584. }
  585.  
  586. /* Given the ascii name of an interface, return a pointer to the structure,
  587.  * or NULLIF if it doesn't exist
  588.  */
  589. struct iface *
  590. if_lookup(name)
  591. char *name;
  592. {
  593.     register struct iface *ifp;
  594.  
  595.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  596.         if(strcmp(ifp->name,name) == 0)
  597.             break;
  598.     return ifp;
  599. }
  600.  
  601. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  602.  * NULLIF otherwise.
  603.  * This is used to tell if an incoming IP datagram is for us, or if it
  604.  * has to be routed.
  605.  */
  606. struct iface *
  607. ismyaddr(addr)
  608. int32 addr;
  609. {
  610.     register struct iface *ifp;
  611.  
  612.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  613.         if(addr == ifp->addr)
  614.             break;
  615.     return ifp;
  616. }
  617.  
  618. /* Given a network mask, return the number of contiguous 1-bits starting
  619.  * from the most significant bit.
  620.  */
  621. static int
  622. mask2width(mask)
  623. int32 mask;
  624. {
  625.     int width,i;
  626.  
  627.     width = 0;
  628.     for(i = 31;i >= 0;i--){
  629.         if(!(mask & (1L << i)))
  630.             break;
  631.         width++;
  632.     }
  633.     return width;
  634. }
  635.  
  636. /* return buffer with name + comment */
  637. char *
  638. if_name(ifp,comment)
  639. struct iface *ifp;
  640. char *comment;
  641. {
  642.     char *result = mallocw( strlen(ifp->name) + strlen(comment) + 1 );
  643.     strcpy( result, ifp->name );
  644.     return strcat( result, comment );
  645. }
  646.  
  647. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  648. int
  649. bitbucket(ifp,bp)
  650. struct iface *ifp;
  651. struct mbuf *bp;
  652. {
  653.     free_p(bp);
  654.     return 0;
  655. }
  656.